home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / ZIP19.ARJ / VMS.C < prev    next >
C/C++ Source or Header  |  1992-08-18  |  19KB  |  760 lines

  1. /*************************************************************************
  2.  *                                                                       *
  3.  * VMS portions copyright (C) 1992 Igor Mandrichenko.                    *
  4.  * Permission is granted to any individual or institution to use, copy,  *
  5.  * or redistribute this software so long as all of the original files    *
  6.  * are included unmodified, that it is not sold for profit, and that     *
  7.  * this copyright notice is retained.                                    *
  8.  *                                                                       *
  9.  *************************************************************************/
  10.  
  11. /*
  12.  *  vms.c (zip) by Igor Mandrichenko    Version 2.1-1
  13.  *
  14.  *  Revision history:
  15.  *  ...
  16.  *  2.1-1       16-feb-1992     I.Mandrichenko  
  17.  *      Get file size from XABFHC and check bytes rest in file before
  18.  *      reading. 
  19.  *  2.1-2       2-mar-1992      I.Mandrichenko
  20.  *      Make code more standard
  21.  *  2.2         21-jun-1992     I.Mandrichenko
  22.  *      Free all allocated space, use more static storage.
  23.  *      Use memcompress() from bits.c (deflation) for block compression.
  24.  *      To revert to old compression method #define OLD_COMPRESS
  25.  */
  26.  
  27. #ifdef VMS                      /* For VMS only ! */
  28.  
  29. #define OLD_COMPRESS    /*To use old compression method define it.*/
  30.  
  31. #include <rms.h>
  32. #include <descrip.h>
  33. #include <syidef.h>
  34.  
  35. #ifndef VAXC
  36.                                 /* This definition may be missed */
  37. struct XAB {
  38.     unsigned char xab$b_cod;
  39.     unsigned char xab$b_bln;
  40.     short int xabdef$$_fill_1;
  41.     char *xab$l_nxt;
  42. };
  43.  
  44. #endif
  45.  
  46. #ifndef SYI$_VERSION
  47. #define SYI$_VERSION 4096       /* VMS 5.4 definition */
  48. #endif
  49.  
  50. #include "zip.h"
  51.  
  52. #define ERR(s)  !((s)&1)
  53.  
  54. #define RET_ERROR 1
  55. #define RET_SUCCESS 0
  56. #define RET_EOF 0
  57.  
  58. #define Kbyte 1024
  59.  
  60. typedef struct XAB *xabptr;
  61.  
  62. /*
  63. *   Extra record format
  64. *   ===================
  65. *   signature       (2 bytes)   = 'I','M'
  66. *   size            (2 bytes)
  67. *   block signature (4 bytes)
  68. *   flags           (2 butes)
  69. *   uncomprssed size(2 bytes)
  70. *   reserved        (4 bytes)
  71. *   data            (size-12 bytes)
  72. *   ....
  73. */
  74.  
  75.  
  76. /*
  77. *   Extra field signature and block signatures
  78. */
  79. #define SIGNATURE "IM"
  80. #define EXTBSL  4               /* Block signature length   */
  81. #define RESL    8
  82.  
  83. #define BC_MASK         07      /* 3 bits for compression type */       
  84. #define BC_STORED       0       /* Stored */
  85. #define BC_00           1       /* 0byte -> 0bit compression */
  86. #define BC_DEFL         2       /* Deflated */
  87.  
  88. struct extra_block
  89. {       ush     im_sig;
  90.         ush     size;
  91.         ulg     block_sig;
  92.         ush     flags;
  93.         ush     length;
  94.         ulg     reserved;
  95.         uch     body[1];        /* The actual size is unknown */
  96. };
  97.  
  98. #define FABSIG  "VFAB"
  99. #define XALLSIG "VALL"
  100. #define XFHCSIG "VFHC"
  101. #define XDATSIG "VDAT"
  102. #define XRDTSIG "VRDT"
  103. #define XPROSIG "VPRO"
  104. #define XKEYSIG "VKEY"
  105. #define VERSIG  "VMSV"
  106. /*
  107. *   Block sizes
  108. */
  109. #define FABL    (cc$rms_fab.fab$b_bln)
  110. #define RABL    (cc$rms_rab.rab$b_bln)
  111. #define XALLL   (cc$rms_xaball.xab$b_bln)
  112. #define XDATL   (cc$rms_xabdat.xab$b_bln)
  113. #define XFHCL   (cc$rms_xabfhc.xab$b_bln)
  114. #define XKEYL   (cc$rms_xabkey.xab$b_bln)
  115. #define XPROL   (cc$rms_xabpro.xab$b_bln)
  116. #define XRDTL   (cc$rms_xabrdt.xab$b_bln)
  117. #define XSUML   (cc$rms_xabsum.xab$b_bln)
  118. #define EXTHL   (4+EXTBSL+RESL)
  119. #define EXTL0   ((FABL + EXTHL)+        \
  120.                 (XFHCL + EXTHL)+        \
  121.                 (XPROL + EXTHL)+        \
  122.                 (XDATL + EXTHL)+        \
  123.                 (XRDTL + EXTHL))
  124.  
  125. #ifdef OLD_COMPRESS
  126. #define PAD     sizeof(uch)
  127. #else
  128. #define PAD     10*sizeof(ush)          /* Two extra bytes for compr. header */
  129. #endif
  130.  
  131. #define PAD0    (5*PAD)                 /* Reserve space for the case when
  132.                                         *  compression failes */
  133. static int _compress();
  134.  
  135. /***********************************
  136.  *   Function get_vms_attributes   *
  137.  ***********************************/
  138.  
  139. static uch *_compress_block();
  140. static int get_vms_version();
  141.  
  142. int get_vms_attributes(z)
  143.   struct zlist *z;
  144. /*
  145.  *      Get file VMS file attributes and store them into extent fields.
  146.  *      Store VMS version also.
  147.  *      On error leave z intact.
  148.  */
  149. {
  150.     int status;
  151.     uch *extra=(uch*)NULL, *scan;
  152.     extent extra_l;
  153.     static struct FAB fab;
  154.     static struct XABSUM xabsum;
  155.     static struct XABFHC xabfhc;
  156.     static struct XABDAT xabdat;
  157.     static struct XABPRO xabpro;
  158.     static struct XABRDT xabrdt;
  159.     xabptr x = (xabptr)NULL, xab_chain = (xabptr)NULL, last_xab = (xabptr)NULL;
  160.     int nk, na;
  161.     int i;
  162.     int rc=RET_ERROR;
  163.     char verbuf[80];
  164.     int verlen = 0;
  165.  
  166.     /*
  167.     *   Initialize RMS control blocks and link them
  168.     */
  169.  
  170.     fab =    cc$rms_fab;
  171.     xabsum = cc$rms_xabsum;
  172.     xabdat = cc$rms_xabdat;
  173.     xabfhc = cc$rms_xabfhc;
  174.     xabpro = cc$rms_xabpro;
  175.     xabrdt = cc$rms_xabrdt;
  176.  
  177.  
  178.     fab.fab$l_xab = (char*)&xabsum;
  179.     /*
  180.     *   Open the file and read summary information.
  181.     */
  182.     fab.fab$b_fns = strlen(z->name);
  183.     fab.fab$l_fna = z->name;
  184.  
  185.     status = sys$open(&fab);
  186.     if (ERR(status))
  187.     {
  188. #ifdef DEBUG
  189.         printf("get_vms_attributes: sys$open for file %s:\n  error status = %d\n",
  190.                z->name, status);
  191. #endif
  192.         goto err_exit;
  193.     }
  194.  
  195.     nk = xabsum.xab$b_nok;
  196.     na = xabsum.xab$b_noa;
  197. #ifdef DEBUG
  198.     printf("%d keys, %d alls\n", nk, na);
  199. #endif
  200.  
  201.     /*
  202.     *   Allocate XABKEY and XABALL blocks ind link them
  203.     */
  204.  
  205.     xabfhc.xab$l_nxt = (char*)&xabdat;
  206.     xabdat.xab$l_nxt = (char*)&xabpro;
  207.     xabpro.xab$l_nxt = (char*)&xabrdt;
  208.     xabrdt.xab$l_nxt = (char*)0L;
  209.  
  210.     xab_chain = (xabptr)(&xabfhc);
  211.     last_xab  = (xabptr)(&xabrdt);
  212.  
  213. #define INIT(ptr,size,init)     \
  214.         if( (ptr = (uch*)malloc(size)) == NULL )        \
  215.         {                                               \
  216.               printf( "get_vms_attributes: Insufficient memory.\n" );   \
  217.                       goto err_exit;                    \
  218.         }                                               \
  219.         *(ptr) = (init);
  220.     /*
  221.     *   Allocate and initialize all needed XABKEYs and XABALLs
  222.     */
  223.     for (i = 0; i < nk; i++)
  224.     {
  225.         struct XABKEY *k;
  226.         INIT(k, XKEYL, cc$rms_xabkey);
  227.         k->xab$b_ref = i;
  228.         if (last_xab != 0L)
  229.             last_xab->xab$l_nxt = (char*)k;
  230.         last_xab = (xabptr)k;
  231.     }
  232.     for (i = 0; i < na; i++)
  233.     {
  234.         struct XABALL *a;
  235.         INIT(a, XALLL, cc$rms_xaball);
  236.         a->xab$b_aid = i;
  237.         if (last_xab != 0L)
  238.             last_xab->xab$l_nxt = (char*)a;
  239.         last_xab = (xabptr)a;
  240.     }
  241.  
  242.     fab.fab$l_xab = (char*)xab_chain;
  243. #ifdef DEBUG
  244.     printf("Dump of XAB chain before DISPLAY:\n");
  245.     for (x = xab_chain; x != 0L; x = x->xab$l_nxt)
  246.         dump_rms_block(x);
  247. #endif
  248.     /*
  249.     *   Get information on the file structure etc.
  250.     */
  251.     status = sys$display(&fab, 0, 0);
  252.     if (ERR(status))
  253.     {
  254. #ifdef DEBUG
  255.         printf("get_vms_attributes: sys$display for file %s:\n  error status = %d\n",
  256.                z->name, status);
  257. #endif
  258.         goto err_exit;
  259.     }
  260.  
  261. #ifdef DEBUG
  262.     printf("\nDump of XAB chain after DISPLAY:\n");
  263.     for (x = xab_chain; x != 0L; x = x->xab$l_nxt)
  264.         dump_rms_block(x);
  265. #endif
  266.  
  267.     fab.fab$l_xab = 0;  /* Keep XABs */
  268.     status = sys$close(&fab);
  269.     if (ERR(status))
  270.     {
  271. #ifdef DEBUG
  272.         printf("get_vms_attributes: sys$close for file %s:\n  error status = %d\n",
  273.                z->name, status);
  274. #endif
  275.         goto err_exit;
  276.     }
  277.  
  278.     extra_l = EXTL0 + nk * (XKEYL + EXTHL) + na * (XALLL + EXTHL);
  279. #ifndef OLD_COMPRESS
  280.     extra_l += PAD0 + (nk+na) * PAD;
  281. #endif
  282.  
  283.     if( verlen = get_vms_version(verbuf,sizeof(verbuf)) )
  284.     {   extra_l += verlen + EXTHL;
  285. #ifndef OLD_COMPRESS
  286.         extra_l += PAD;
  287. #endif
  288.     }
  289.  
  290.     if ((scan = extra = (uch *) malloc(extra_l)) == (uch*)NULL)
  291.     {
  292. #ifdef DEBUG
  293.         printf("get_vms_attributes: Insufficient memory to allocate extra buffer\n");
  294. #endif
  295.         goto err_exit;
  296.     }
  297.  
  298.  
  299.     if( verlen > 0 )
  300.         scan = _compress_block(scan,verbuf, verlen, VERSIG);
  301.  
  302.     /*
  303.      *  Zero all unusable fields to improve compression
  304.      */
  305.     fab.fab$b_fns = fab.fab$b_shr = fab.fab$b_dns = fab.fab$b_fac = 0;
  306.     fab.fab$w_ifi = 0;
  307.     fab.fab$l_stv = fab.fab$l_sts = fab.fab$l_ctx = 0;
  308.     fab.fab$l_fna = fab.fab$l_nam = fab.fab$l_xab = fab.fab$l_dna = (char*)0L;
  309.  
  310. #ifdef DEBUG
  311.     dump_rms_block( &fab );
  312. #endif
  313.     scan = _compress_block(scan,&fab, FABL, FABSIG);
  314.     for (x = xab_chain; x != 0L;)
  315.     {
  316.         int bln;
  317.         char *sig;
  318.         xabptr next;
  319.  
  320.         next = (xabptr)(x->xab$l_nxt);
  321.         x->xab$l_nxt = 0;
  322.  
  323.         switch (x->xab$b_cod)
  324.         {
  325.             case XAB$C_ALL:
  326.                 bln = XALLL;
  327.                 sig = XALLSIG;
  328.                 break;
  329.             case XAB$C_KEY:
  330.                 bln = XKEYL;
  331.                 sig = XKEYSIG;
  332.                 break;
  333.             case XAB$C_PRO:
  334.                 bln = XPROL;
  335.                 sig = XPROSIG;
  336.                 break;
  337.             case XAB$C_FHC:
  338.                 bln = XFHCL;
  339.                 sig = XFHCSIG;
  340.                 break;
  341.             case XAB$C_DAT:
  342.                 bln = XDATL;
  343.                 sig = XDATSIG;
  344.                 break;
  345.             case XAB$C_RDT:
  346.                 bln = XRDTL;
  347.                 sig = XRDTSIG;
  348.                 break;
  349.             default:
  350.                 bln = 0;
  351.                 sig = 0L;
  352.                 break;
  353.         }
  354.         if (bln > 0)
  355.             scan = _compress_block(scan,x, bln, sig);
  356.         x = next;
  357.     }
  358.  
  359.     z->ext = z->cext = scan-extra;
  360.     z->extra = z->cextra = (char*)extra;
  361.     rc = RET_SUCCESS;
  362.  
  363. err_exit:
  364.     /*
  365.     * Give up all allocated blocks
  366.     */
  367.     for(x = (struct XAB *)xab_chain; x != 0L; )
  368.     {   struct XAB *next;
  369.         next = (xabptr)(x->xab$l_nxt);
  370.         if( x->xab$b_cod == XAB$C_ALL || x->xab$b_cod == XAB$C_KEY )
  371.                 free(x);
  372.         x = next;
  373.     }
  374.     return rc;
  375. }
  376.  
  377. static int get_vms_version(verbuf,len)
  378. char *verbuf;
  379. int len;
  380. {   int i = SYI$_VERSION;
  381.     int verlen = 0;
  382.     struct dsc$descriptor version;
  383.     char *m;
  384.  
  385.     version.dsc$a_pointer = verbuf;
  386.     version.dsc$w_length  = len-1;
  387.     version.dsc$b_dtype   = DSC$K_DTYPE_B;
  388.     version.dsc$b_class   = DSC$K_CLASS_S;
  389.  
  390.     if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
  391.         return 0;
  392.  
  393.     /* Cut out trailing spaces "V5.4-3   " -> "V5.4-3" */
  394.     for(m=verbuf+verlen,i=verlen-1; i>0 && verbuf[i]==' '; --i) 
  395.         --m;
  396.     *m = 0;
  397.  
  398.     /* Cut out release number "V5.4-3" -> "V5.4" */
  399.     if( (m=strrchr(verbuf,'-')) != (char*)NULL )
  400.         *m = 0;
  401.     return strlen(verbuf)+1;    /* Transmit ending 0 too */
  402. }
  403.  
  404. #define CTXSIG ((ulg)('CtXx'))
  405.  
  406. typedef struct user_context
  407. {
  408.     ulg sig;
  409.     struct FAB *fab;
  410.     struct RAB *rab;
  411.     ulg size,rest;
  412.     int status;
  413. } Ctx, *Ctxptr;
  414.  
  415. Ctx init_ctx =  
  416. {       CTXSIG,
  417.         0L,
  418.         0L,
  419.         0L,
  420.         0L,
  421.         0
  422. };
  423.  
  424. #define CTXL    sizeof(Ctx)
  425. #define CHECK_RAB(_r) ( (_r) != 0 &&                            \
  426.                         (_r) -> rab$b_bid == RAB$C_BID &&       \
  427.                         (_r) -> rab$b_bln == RAB$C_BLN &&       \
  428.                         (_r) -> rab$l_ctx != 0L     &&          \
  429.                         (_r) -> rab$l_fab != 0L )
  430.  
  431. /**************************
  432.  *   Function vms_open    *
  433.  **************************/
  434. struct RAB *vms_open(name)
  435.     char *name;
  436. {
  437.     struct RAB *rab;
  438.     struct FAB *fab;
  439.     struct XABFHC *fhc;
  440.     Ctxptr ctx;
  441.  
  442.     if ((fab = (struct FAB *) malloc(FABL)) == (struct FAB *)NULL)
  443.         return 0;
  444.     if ((rab = (struct RAB *) malloc(RABL)) == (struct RAB *)NULL)
  445.     {
  446.         free(fab);
  447.         return 0;
  448.     }
  449.     if ((fhc = (struct XABFHC *) malloc(XFHCL)) == (struct XABFHC *)NULL)
  450.     {
  451.         free(rab);
  452.         free(fab);
  453.         return 0;
  454.     }
  455.     if ((ctx = (Ctxptr) malloc(CTXL)) == (Ctxptr)NULL)
  456.     {
  457.         free(fhc);
  458.         free(fab);
  459.         free(rab);
  460.         return 0;
  461.     }
  462.     *fab = cc$rms_fab;
  463.     *rab = cc$rms_rab;
  464.     *fhc = cc$rms_xabfhc;
  465.  
  466.     fab->fab$l_fna = name;
  467.     fab->fab$b_fns = strlen(name);
  468.     fab->fab$b_fac = FAB$M_GET | FAB$M_BIO;
  469.     fab->fab$l_xab = (char*)fhc;
  470.  
  471.     if (ERR(sys$open(fab)))
  472.     {
  473.         sys$close(fab);
  474.         free(fhc);
  475.         free(fab);
  476.         free(rab);
  477.         free(ctx);
  478.         return 0;
  479.     }
  480.  
  481.     rab->rab$l_fab = fab;
  482.     rab->rab$l_rop = RAB$M_BIO;
  483.  
  484.     if (ERR(sys$connect(rab)))
  485.     {
  486.         sys$close(fab);
  487.         free(fab);
  488.         free(rab);
  489.         free(ctx);
  490.         return 0;
  491.     }
  492.  
  493.     *ctx = init_ctx;
  494.     ctx->rab = rab;
  495.     ctx->fab = fab;
  496.  
  497.     if( fhc->xab$l_ebk > 0 )
  498.         ctx->size = ctx->rest = ( fhc->xab$l_ebk-1 ) * 512 + fhc->xab$w_ffb;
  499.     else
  500.         ctx->size = ctx->rest = 0;
  501.     free(fhc);
  502.     fab -> fab$l_xab = 0;
  503.     rab->rab$l_ctx = (long)ctx;
  504.     return rab;
  505. }
  506.  
  507. /**************************
  508.  *   Function vms_close   *
  509.  **************************/
  510. int vms_close(rab)
  511.     struct RAB *rab;
  512. {
  513.     struct FAB *fab;
  514.     Ctxptr ctx;
  515.  
  516.     if (!CHECK_RAB(rab))
  517.         return RET_ERROR;
  518.     fab = (ctx = (Ctxptr)(rab->rab$l_ctx))->fab;
  519.     sys$close(fab);
  520.  
  521.     free(fab);
  522.     free(rab);
  523.     free(ctx);
  524.  
  525.     return RET_SUCCESS;
  526. }
  527.  
  528. /**************************
  529.  *   Function vms_rewind  *
  530.  **************************/
  531. int vms_rewind(rab)
  532.     struct RAB *rab;
  533. {
  534.     Ctxptr ctx;
  535.  
  536.     int status;
  537.     if (!CHECK_RAB(rab))
  538.         return RET_ERROR;
  539.  
  540.     ctx = (Ctxptr) (rab->rab$l_ctx);
  541.     if (ERR(status = sys$rewind(rab)))
  542.     {
  543.         ctx->status = status;
  544.         return RET_ERROR;
  545.     }
  546.  
  547.     ctx->status = 0;
  548.     ctx->rest = ctx->size;
  549.     
  550.     return RET_SUCCESS;
  551. }
  552.  
  553. /**************************
  554.  *   Function vms_read    *
  555.  **************************/
  556. int vms_read(rab, buf, size)
  557.     struct RAB *rab;
  558. char *buf;
  559. int size;
  560. /*
  561. *       size must be greater or equal to 512 !
  562. */
  563. {
  564.     int status;
  565.     Ctxptr ctx;
  566.  
  567.     ctx = (Ctxptr)rab->rab$l_ctx;
  568.  
  569.     if (!CHECK_RAB(rab))
  570.         return 0;
  571.  
  572.     if (ctx -> rest <= 0)
  573.         return 0;               /* Eof */
  574.  
  575.     if(size > 16*Kbyte)         /* RMS can not read too much */
  576.         size = 16*Kbyte;
  577.     else
  578.         size &= ~511L;
  579.  
  580.     rab->rab$l_ubf = buf;
  581.     rab->rab$w_usz = size;
  582.     status = sys$read(rab);
  583.     if (!ERR(status) && rab->rab$w_rsz > 0)
  584.     {
  585.         ctx -> status = 0;
  586.         ctx -> rest -= rab->rab$w_rsz;
  587.         return rab->rab$w_rsz;
  588.     }
  589.     else
  590.     {
  591.         ctx->status = (status==RMS$_EOF ? 0:status);
  592.         if(status == RMS$_EOF)
  593.                 ctx -> rest = 0L;
  594.         return 0;
  595.     }
  596. }
  597.  
  598. /**************************
  599.  *   Function vms_error   *
  600.  **************************/
  601. int vms_error(rab)
  602.     struct RAB *rab;
  603. {
  604.     if (!CHECK_RAB(rab))
  605.         return RET_ERROR;
  606.     return ((Ctxptr) (rab->rab$l_ctx))->status;
  607. }
  608.  
  609.  
  610. dump_rms_block(p)
  611.     unsigned char *p;
  612. {
  613.     unsigned char bid, len;
  614.     int err;
  615.     char *type;
  616.     char buf[132];
  617.     int i;
  618.  
  619.     err = 0;
  620.     bid = p[0];
  621.     len = p[1];
  622.     switch (bid)
  623.     {
  624.         case FAB$C_BID:
  625.             type = "FAB";
  626.             break;
  627.         case XAB$C_ALL:
  628.             type = "xabALL";
  629.             break;
  630.         case XAB$C_KEY:
  631.             type = "xabKEY";
  632.             break;
  633.         case XAB$C_DAT:
  634.             type = "xabDAT";
  635.             break;
  636.         case XAB$C_RDT:
  637.             type = "xabRDT";
  638.             break;
  639.         case XAB$C_FHC:
  640.             type = "xabFHC";
  641.             break;
  642.         case XAB$C_PRO:
  643.             type = "xabPRO";
  644.             break;
  645.         default:
  646.             type = "Unknown";
  647.             err = 1;
  648.             break;
  649.     }
  650.     printf("Block @%08X of type %s (%d).", p, type, bid);
  651.     if (err)
  652.     {
  653.         printf("\n");
  654.         return;
  655.     }
  656.     printf(" Size = %d\n", len);
  657.     printf(" Offset - Hex - Dec\n");
  658.     for (i = 0; i < len; i += 8)
  659.     {
  660.         int j;
  661.         printf("%3d - ", i);
  662.         for (j = 0; j < 8; j++)
  663.             if (i + j < len)
  664.                 printf("%02X ", p[i + j]);
  665.             else
  666.                 printf("   ");
  667.         printf(" - ");
  668.         for (j = 0; j < 8; j++)
  669.             if (i + j < len)
  670.                 printf("%03d ", p[i + j]);
  671.             else
  672.                 printf("    ");
  673.         printf("\n");
  674.     }
  675. }
  676.  
  677. #ifdef OLD_COMPRESS
  678. # define BC_METHOD      BC_00
  679. # define        COMP_BLK(to,tos,from,froms) _compress( from,to,froms )
  680. #else
  681. # define BC_METHOD      BC_DEFL
  682. # define        COMP_BLK(to,tos,from,froms) memcompress(to,tos,from,froms)
  683. #endif
  684.  
  685. static uch *_compress_block(to,from,size,sig)
  686. register struct extra_block *to;
  687. uch *from,*sig;
  688. int size;
  689. {                               
  690.         ulg cl;
  691.         to -> im_sig =  *(ush*)SIGNATURE;
  692.         to -> block_sig =       *(ulg*)(sig);
  693.         to -> flags =           BC_METHOD;
  694.         to -> length =  size;
  695. #ifdef DEBUG
  696.         printf("\nmemcompr(%d,%d,%d,%d)\n",&(to->body[0]),size+PAD,from,size);
  697. #endif
  698.         cl = COMP_BLK( &(to->body[0]), size+PAD, from, size );
  699. #ifdef DEBUG
  700.         printf("Compressed to %d\n",cl);
  701. #endif
  702.         if( cl >= size )
  703.         {       memcpy(&(to->body[0]), from, size);
  704.                 to->flags = BC_STORED;
  705.                 cl = size;
  706. #ifdef DEBUG
  707.                 printf("Storing block...\n");
  708. #endif
  709.         }
  710.         return (uch*)(to) + (to->size = cl + EXTBSL + RESL) + 4;
  711. }
  712.  
  713. #define NBITS 32
  714.  
  715. static int _compress(from,to,size)
  716. uch *from,*to;
  717. int size;
  718. {
  719.     int off=0;
  720.     ulg bitbuf=0;
  721.     int bitcnt=0;
  722.     int i;
  723.  
  724. #define _BIT(val,len)   {                       \
  725.         if(bitcnt + (len) > NBITS)              \
  726.             while(bitcnt >= 8)                  \
  727.             {                                   \
  728.                 to[off++] = (uch)bitbuf;        \
  729.                 bitbuf >>= 8;                   \
  730.                 bitcnt -= 8;                    \
  731.             }                                   \
  732.         bitbuf |= ((ulg)(val))<<bitcnt;         \
  733.         bitcnt += len;                          \
  734.     }
  735.  
  736. #define _FLUSH  {                               \
  737.             while(bitcnt>0)                     \
  738.             {                                   \
  739.                 to[off++] = (uch)bitbuf;        \
  740.                 bitbuf >>= 8;                   \
  741.                 bitcnt -= 8;                    \
  742.             }                                   \
  743.         }
  744.  
  745.     for(i=0; i<size; i++)
  746.     {
  747.         if( from[i] )
  748.         {
  749.                 _BIT(1,1);
  750.                 _BIT(from[i],8);
  751.         }
  752.         else
  753.             _BIT(0,1);
  754.     }
  755.     _FLUSH;
  756.     return off;
  757. }
  758.  
  759. #endif                          /* ?VMS */
  760.